<template>
  <div>
    <!--
    <el-row class="top">
      <el-col :span="2" align="right" style="height: 100%;overflow: hidden;">
        <el-image style="width: 40px; height: 40px;padding: 0;margin: 0" :src="require('/src/assets/logo.png')" fit="fill"/>
      </el-col>
      <el-col :span="6">
        <span class="el-icon-magic-stick lg" style="width: 30px"/>
        <span>Cola Designer</span>
        <a style="margin: 0 4px;" href='https://gitee.com/colaiven/cola-designer' target="_blank">
          <el-image style="width: 50px; height: 16px;padding: 0;margin: 0" src='https://gitee.com/colaiven/cola-designer/badge/star.svg?theme=dark' alt='star'/>
        </a>
      </el-col>
      <el-col :span="16" @click.self.native="outBlur">
        <el-button size="mini" @click="preview" style="margin: 10px 10px;
            background: #49586e;color: #fff;float: right">预览</el-button>
        <el-button size="mini" @click="submitDesign" style="margin: 10px 5px;background: #d5d9e2;float: right">保存</el-button>
        <div style="float: right;margin: 1px 10px;" class="configBtn" @click="clearDesign">
          <i style="font-size: 22px;" class="el-icon-delete"/>
        </div>
        <div style="float: right;margin: 0 10px;">
          <el-dropdown @command="exportCommand">
            <span class="el-dropdown-link">
              导出<i class="el-icon-arrow-down el-icon--right"></i>
            </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item command="img">图片</el-dropdown-item>
              <el-dropdown-item command="json">设计文件</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </div>
        <div style="float: right;margin: 0 10px;" @click="importDesign()">
          <span style="font-size: 14px;cursor: pointer">导入</span>
        </div>
      </el-col>
    </el-row>
    -->
    <layout-top :menuStatus="menuStatus" @onLayerClick="onLayerClick" @preview="preview" @save="submitDesign"></layout-top>
    <div class="layout-main" :style="{height: (windowHeight-61)+'px',background: 'url('+require('@/assets/port.png')+') repeat'}" @click.self="outBlur">
      <div class="layout-main-left" ref="left">
        <layout-aside v-if="true"
                      @dragStart="dragStart"
                      :selectedComponents="cacheComponents"
                      :currentCptIndex="currentCptIndex"
                      :menuStatus="menuStatus"
                      @onLock="lockTarget"
                      @onHide="hideTarget"
                      @onSelect="onLayerSelect"
                      @copyCpt="copyCpt"
                      @delCpt="delCpt"/>
      </div>
      <div class="layout-main-center"  @click.self="outBlur">
        <div class="layout-main-center__inner" ref="inner">
          <div style="height: 10px;margin: 10px 0 0 20px;" :style="{width: designData.scaleX*containerScale+'px'}">
            <ScaleMarkX :max="designData.scaleX"/><!--顶部刻度线-->
          </div>
          <div style="position: absolute;width: 10px; margin-left: 10px;" :style="{height:designData.scaleX*containerScale / designData.scaleX * designData.scaleY+'px'}">
            <ScaleMarkY :max="designData.scaleY"/><!--左侧刻度线-->
          </div>
          <div class="webContainer"
               id="webContainer"
               :style="{
                width:designData.scaleX+'px',
                height: designData.scaleY+'px',
                background: designData.bgColor,
                backgroundImage: designData.bgImg ? 'url('+designData.bgImg+')':'none',transform: 'scale('+containerScale+')',
                backgroundSize: '100% 100%'
                }"
               ref="webContainer"
               @dragover="allowDrop"
               @drop="drop"
               @mousedown="onMousedownSelect"
               @contextmenu="onContainerContextmenu($event)"
          >
            <!-- 单个组件 -->
            <template v-if="true">
              <div v-for="(item, index) in cacheComponents" :key="item.id">

                <edit-group v-if="item.isGroup"
                            :ref="'editGroup' + item.id"
                            v-show="!item.status.hide"
                            :item="item"
                            :index="index"
                            :currentCptIndex="currentCptIndex"
                            :selected="!!cacheChoices[item.id]"
                            :length="cacheComponents.length"
                            @mousedown.native="showConfigBar($event,item,index)"
                            @contextmenu.native="onContextmenu($event, item, index)"
                />

                <edit-single v-else
                             :ref="'editSingle' + item.id"
                             v-show="!item.status.hide"
                             :item="item"
                             :index="index"
                             :currentCptIndex="currentCptIndex"
                             :selected="!!cacheChoices[item.id]"
                             :length="cacheComponents.length"
                             @mousedown.native="showConfigBar($event,item,index)"
                             @contextmenu.native="onContextmenu($event, item, index)"
                > </edit-single>
              </div>

            </template>

            <select-box :position="mousePosition" :is-select="isSelect" :scale="containerScale"></select-box>
          </div>
        </div>

        <div class="layout-main-center__bottom">
          <div>
          </div>
          <div class="gap-wrap">
            <el-dropdown trigger="click" @command="onScaleCommand">
              <span class="el-dropdown-link">
                {{ scaleText }}<i class="el-icon-arrow-down el-icon--right"></i>
              </span>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item v-for="item in scaleList" :key="item.value" :command="item.value">{{ item.text }}</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
            <div style="width: 120px;">
              <el-slider v-model="containerScale" :min="0.3" :max="2" :step="0.01"/>
            </div>
          </div>

        </div>

      </div>
      <div style="float: right;height: 100%;overflow: hidden; transition: all 0.4s;" :style="{width:configBarWidth-6+'px'}">
        <config-bar ref="configBar" :currentCpt.sync="currentCpt" :designData.sync="designData" @refreshCptData="refreshCptData" :height="windowHeight"/><!--右侧属性栏-->
      </div>
    </div>
    <input v-show="false" type="file" id="files" ref="refFile" @change="fileLoad" accept=".cd">

    <context-menu ref="contextMenu" :data="menus" @click="onMenuClick"></context-menu>

  </div>
</template>

<script>
import layoutTop from '@/components/desinger/layout-top'
import ComponentBar from "@/views/designer/componentBar";
import ConfigBar from "@/views/designer/configBar";
import html2canvas from 'html2canvas';
import {getReportdashboardInfoId, postReportdashboardSave} from '@/api/dashboard'
import {fileDownload, base64toFile} from '@/utils/FileUtil'
import env from "/env";
import {clearCptInterval} from "@/utils/refreshCptData";
import ScaleMarkX from "@/views/designer/components/scaleMark/ScaleMarkX";
import ScaleMarkY from "@/views/designer/components/scaleMark/ScaleMarkY";
import layoutAside from './components/layoutAside'
import contextMenu from '@/components/desinger/contextMenu'
import selectBox from './components/selectBox'
import EditSingle from  './components/EditSingle'
import EditGroup from './components/EditGroup'
import uploadAction from '@/components/common/file/uploadAction'
import bus from '@/utils/bus'

import contextMixin from './mixins/context-mixin'
import {getConfigByCptKey} from "@/package/tools"

export default {
  name: 'design-index',
  mixins: [contextMixin],
  components: {
    layoutAside,
    layoutTop,
    ScaleMarkY,
    ScaleMarkX,
    ConfigBar,
    contextMenu,
    selectBox,
    EditSingle,
    EditGroup
  },
  provide() {
    return {
      wrapper: this
    }
  },
  data() {
    return {
      windowWidth:0,
      windowHeight:0,
      fileUrl:env.fileUrl,
      cptBarWidth: 450,
      configBarWidth: 400,
      copyDom: '',
      designData:{
        id:'',
        reportId: '',
        title: '我的大屏',
        scaleX: 1920,
        scaleY: 1080,
        version:'',
        bgColor:'#2B3340',
        simpleDesc:'',
        bgImg:'',
        viewCode:'',
        screenAdapter: 'auto', // 适配方式
        components:[],
        constants: {} // 常量
      },
      cacheComponents:[],
      currentCptIndex: -1,
      currentCpt: {cptOption: undefined},
      containerScale:1,
      cacheChoices:{},
      cacheChoicesFixed:{}, //记录移动前选中组件的位置 自定义事件内部无法处理，放在了外面。
      menus: [],
      menuStatus: { // 展开/收缩状态
        chart: true,
        layer: true,
        config: true
      },
      scaleList: [
        {text: '200%', value: 2},
        {text: '150%', value: 1.5},
        {text: '100%', value: 1},
        {text: '50%', value: 0.5},
        {text: '自适应', value: 0}
      ]
    }
  },
  created() {
  },
  mounted() {
    this.loadCacheData();
    const that = this;

    bus.$on('update-constants', (key, val) => {
      const obj = {}
      obj[key] = val
      this.designData.constants = Object.assign({}, this.designData.constants, obj)
    })

    bus.$on('delete-constants', key => {
      delete this.designData.constants[key]
      this.designData.constants = Object.assign({}, this.designData.constants)
    })

    window.addEventListener("keydown",(event)=>{
      if (that.currentCptIndex !== -1){
        let key = event.key
        switch (key) {//方向键移动当前组件
          case 'ArrowDown':
            that.currentCpt.cptY += 1;
            break;
          case 'ArrowUp':
            that.currentCpt.cptY -= 1;
            break;
          case 'ArrowLeft':
            that.currentCpt.cptX -= 1
            break;
          case 'ArrowRight':
            that.currentCpt.cptX += 1
            break;
        }
      }

      if(event.key === ' ') {
        // 按空格键，可以拖动
        console.info('空格键')
      }
    })
    // window.addEventListener('keyup', (event) => {
    //   console.info(event.key)
    // })
    window.onresize = () => {
      return (() => {
        that.initContainerSize()
      })();
    };
  },
  methods: {
    initConstants() {
      const map = {}
      const query = location.href.split('?')[1]
      if(query) {
        const arr = query.split('&')
        arr.forEach(str => {
          const kv = str.split('=')
          map[kv[0]] = kv[1]
        })
      }
      return map
    },
    initContainerSize(){
      this.windowWidth = document.documentElement.clientWidth
      this.windowHeight = document.documentElement.clientHeight

      const leftWidth = this.$refs.left.getBoundingClientRect().width

      let tempWidth = this.windowWidth - leftWidth - this.configBarWidth;
      this.containerScale = Math.round(tempWidth / this.designData.scaleX * 100) / 100
    },
    exportCommand(command) {
      if(command === 'img'){
        html2canvas(this.$refs.webContainer).then(canvas => {
          const canvasData = canvas.toDataURL("image/jpeg");
          fileDownload(canvasData,this.designData.title+'.png');
        })
      }else if(command === 'json'){
        this.designData.components = this.cacheComponents;
        this.designData.version = env.version;
        const data = JSON.stringify(this.designData)
        let uri = 'data:text/csv;charset=utf-8,\ufeff' + encodeURIComponent(data);//encodeURIComponent解决中文乱码
        fileDownload(uri,this.designData.title+'.cd');
      }
    },
    importDesign(){
      this.$refs.refFile.dispatchEvent(new MouseEvent('click'))
    },
    fileLoad(){
      const that = this;
      const selectedFile = this.$refs.refFile.files[0];
      const reader = new FileReader();
      reader.readAsText(selectedFile);
      reader.onload = function() {
        const fileJson = JSON.parse(this.result);//文件大小、合法性待校验
        if (!fileJson.version || fileJson.version !== env.version){
          that.$message.error('导入失败，与当前版本不一致');
        }else{
          fileJson.id = that.designData.id
          that.designData = fileJson;
          that.cacheComponents = fileJson.components;
          that.designData.components = [];
          that.$message.success('导入成功');
        }
      }
      this.$refs.refFile.value =''
    },
    clearDesign(){
      this.$confirm('此操作将会清空图层，是否继续？', '警告', {
        confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning'
      }).then(() => {
        this.cacheComponents = [];
        this.designData.components = [];
        this.currentCpt = {};
        localStorage.removeItem('designCache');
        clearCptInterval(null, true);
        this.$message.success("清除成功");
      }).catch(() => {});
    },
    loadCacheData(){
      const loading = this.$loading({
        lock: true, text: '加载中', spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      });
      if ('preview' === env.active){
        const cacheStr = localStorage.getItem('designCache');
        if (cacheStr){
          this.designData = JSON.parse(cacheStr);
          if (!this.designData.version || this.designData.version !== env.version){
            localStorage.removeItem('designCache');
            this.$message.success("发现旧版缓存，已清除");
          }else{
            this.cacheComponents = this.designData.components;
            this.designData.components = [];//强迫症
          }
        }
        this.designData.version = env.version;
        this.initContainerSize();
        loading.close();
      }else{
        const id = this.$route.query.id;
        if (id){
          getReportdashboardInfoId(id).then(res => {
            loading.close();
            if(res) {
              if(res.id) {
               res.components.forEach(comp => {
                 comp.cptOption = JSON.parse(comp.cptOption)
                 comp.status = JSON.parse(comp.status)
                 if(comp.isGroup) {
                   comp.collapsed = false
                   comp.groupList = JSON.parse(comp.groupList)
                 }
               })
                if(res.constants) {
                  res.constants = JSON.parse(res.constants)
                } else {
                  res.constants = this.initConstants()
                }
                this.designData = res
                this.cacheComponents = this.designData.components
              } else {
                this.designData.title = res.reportName
              }

            }
            this.designData.reportId = id
            this.initContainerSize();
          })
        }else{
          this.$message.error('当前为DEV模式，请从管理端进入')
        }
      }
    },
    copyCpt(item){
      let copyItem = JSON.parse(JSON.stringify(item))
      copyItem.cptX = item.cptX+30//复制的组件向右下偏移
      copyItem.cptY = item.cptY+30
      copyItem.id = require('uuid').v1();
      this.cacheComponents.push(copyItem);
      this.currentCptIndex = this.cacheComponents.length - 1//聚焦到复制的组件
    },
    refreshCptData(){
      const refName = this.currentCpt.id
      const singleRef = this.$refs['editSingle' + this.currentCpt.id][0]

      if(!singleRef.$refs[refName].refreshCptData){
        this.$message.warning('当前图层还未实现refreshCptData方法')
      }else {
        singleRef.$refs[refName].refreshCptData();// 刷新子组件数据，refs为组建名加index
      }
    },
    outBlur(){//取消聚焦组件
      console.info('bblur')
      this.selectedIds = []
      this.currentCptIndex = -1;
      this.currentCpt = {};
      this.cacheChoices = {}
    },
    submitDesign() {//保存
      const id = this.$route.query.id;

      if ('preview'===env.active){
        this.designData.components = this.cacheComponents;
        localStorage.setItem('designCache', JSON.stringify(this.designData));
        this.$message.success('已保存')
      }else {
        const that = this;
        if(!id){
          that.$message.error('更新异常')
          return;
        }
        const loading = this.$loading({
          lock: true, text: '保存中', spinner: 'el-icon-loading',
          background: 'rgba(0, 0, 0, 0.7)'
        });

        const components = JSON.parse(JSON.stringify(this.cacheComponents))
        components.forEach(comp => {
          comp.cptOption = JSON.stringify(comp.cptOption)
          comp.status = JSON.stringify(comp.status)
          comp.reportId = id
          if(comp.isGroup) {
            comp.groupList = JSON.stringify(comp.groupList)
          }
        })
        this.designData.components = components
        html2canvas(that.$refs.webContainer, {
          allowTaint: true,
          useCORS: true
        }).then(canvas => {
          const canvasData = canvas.toDataURL("image/jpeg");
          let file = base64toFile(canvasData,that.designData.title+'.png');
          const param = {
            file,
            xtlx: 'dashboard'
          }
          uploadAction.upload(param, '/file/uploadOss').then(res => {
            const url = res.url

            const param = {
              ...this.designData,
              screenShot: url
            }
            if(param.constants) {
              param.constants = JSON.stringify(param.constants)
            }

            postReportdashboardSave(param).then(res => {
              loading.close();
              this.$message.success('保存成功!')
            })
          })
          // uploadFileApi(that.designData.id+'.png',fileFormData).then(res => {//上传预览图
          //   that.designData.designImgPath = res.data
          //   that.designData.components = JSON.stringify(this.cacheComponents)
          //   saveOrUpdateApi(this.designData).then(res2 => {
          //     loading.close();
          //     that.$message.success(res2.msg);
          //   })
          // })
          loading.close();
        })
      }
    },
    preview() {//预览按钮
      const id = this.$route.query.id || ''

      const components = JSON.parse(JSON.stringify(this.cacheComponents))

      this.designData.components = components;
      localStorage.setItem('designCache', JSON.stringify(this.designData));
      let routeUrl = this.$router.resolve({
        path: "/preview"
      });
      window.open(routeUrl.href, '_blank');
    },
    delCpt(cpt,index) {
      this.$confirm('删除'+cpt.cptTitle+'组件?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        //记录一个bug，v-for key值重复导致页面渲染数据错乱。在丢下组件时实用uuid作为key解决。
        this.currentCpt = {};
        this.cacheComponents.splice(index, 1);
        const childId = this.$refs[cpt.cptKey+index][0].uuid
        clearCptInterval(childId);
      }).catch(() => {});
    },
    onLayerSelect(event, item) {
      if(!item) {
        return
      }
      const index = this.cacheComponents.findIndex(o => o.id === item.id)
      this.showConfigBar(event, item, index)
    },
    showConfigBar(e, item, index) {//刷新属性栏数据，页面上拖动的组件执行click事件来更新组件的属性栏
      if(e && e instanceof MouseEvent) {
        e.stopPropagation()
        e.preventDefault()
      }

      if(this.cacheChoices[item.id]) {
        return
      }

      if(item.status.lock) {
        return
      }
      this.currentCpt = item;
      this.currentCptIndex = index;
      // if(this.$refs['div'+item.cptKey+index]){
      //   this.$refs['div'+item.cptKey+index][0].focus();//聚焦 用于多选移动
      // }


      if(!e.ctrlKey){//未按住ctrl键
        this.cacheChoices = {}
      }
      this.$refs['configBar'].showCptConfig(item);
      this.cacheChoices[item.id]=item
      this.cacheChoicesFixed[item.id]=JSON.parse(JSON.stringify(item))
    },
    dragStart(copyDom) {//从组件栏拿起组件
      this.copyDom = copyDom;
      copyDom.draggable = false;
    },
    allowDrop(e) {e.preventDefault()},
    drop(e) {//从组件栏丢下组件
      if(!this.copyDom) return
      let config = this.copyDom.getAttribute('config')

      if(config) {
        config = JSON.parse(this.copyDom.getAttribute('config'))
      } else {
        const cptKey = this.copyDom.getAttribute('cptKey')
        config = getConfigByCptKey(cptKey)
      }

      let maxZ =  this.cacheComponents.map(o => o.cptZ).sort().reverse()[0]
      if(!maxZ) {
        maxZ = 1
      } else {
        maxZ ++
      }

      let eventX = e.clientX; // 结束在屏幕的x坐标
      let eventY = e.clientY; // 结束在屏幕的y坐标
      const containerTopLeft = this.getDomTopLeftById('webContainer')

      eventX = (eventX - containerTopLeft.left) / this.containerScale
      eventY = (eventY - containerTopLeft.top) / this.containerScale

      // if(config.option.cptDataForm){//2022-01-24：将静态数据、api、sql用三个字段存储，配置项未填写apiUrl字段和sql字段在此处赋默认值
      //   if (!config.option.cptDataForm.apiUrl){
      //     config.option.cptDataForm.apiUrl = '/design/test'
      //   }
      //   if(!config.option.cptDataForm.sql){
      //     config.option.cptDataForm.sql = 'select username from sys_user limit 1'
      //   }
      // }
      const option = config.option || config.options
      let cpt = {
        cptTitle:config.name,
        icon: config.icon,
        cptKey: config.cptKey,
        cptOptionKey:config.cptOptionKey ? config.cptOptionKey : config.cptKey+'-option',
        cptOption: option,
        cptX: Math.round(eventX),
        cptY: Math.round(eventY),
        cptZ: maxZ,
        cptWidth: config.width ? config.width:400,
        cptHeight: config.height ? config.height : 300,
        cptRotate: 0,
        id: require('uuid').v1(),
        status: {
          lock: false,
          hide: false
        }
      }
      this.copyDom = ''
      this.cacheComponents.unshift(cpt);
      this.cacheChoices = {}//多选清空
      this.showConfigBar({}, cpt, this.cacheComponents.length - 1)//丢下组件后刷新组件属性栏
      this.$refs['configBar'].showCptConfig();
    },
    getDomTopLeftById(id) {
      let dom = document.getElementById(id)
      let top = 0
      let left = 0
      if (dom != null) {
        top = dom.getBoundingClientRect().top
        left = dom.getBoundingClientRect().left
      }
      return { top: top, left: left }
    },
    onLayerClick(key) {
      this.menuStatus[key] = !this.menuStatus[key]
      if(key === 'config') {
        if(this.menuStatus.config) {
          this.configBarWidth = 400
        } else {
          this.configBarWidth = 6
        }
      }

      setTimeout(() => {
        this.initContainerSize()
      }, 500)
    },
    onScaleCommand(command) {
      if(command !== 0) {
        this.containerScale = command
      } else {
        this.initContainerSize()
      }
    }
  },
  computed: {
    scaleText() {
      return parseInt(this.containerScale * 100) + '%'
    }
  },
  directives: {
    resize(el, binding, vNode) {//组件拉伸，移动位置
      el.onmousedown = function (e) {
        const that = vNode.context;
        const scaleClientX = e.clientX / that.containerScale;
        const scaleClientY = e.clientY / that.containerScale;
        const rbX = scaleClientX - el.parentNode.offsetWidth;
        const rbY = scaleClientY - el.parentNode.offsetHeight;
        const ltX = scaleClientX + el.parentNode.offsetWidth;
        const ltY = scaleClientY + el.parentNode.offsetHeight;
        const disX = scaleClientX - el.parentNode.offsetLeft;
        const disY = scaleClientY - el.parentNode.offsetTop;
        let cptWidth, cptHeight, cptX, cptY;

        document.onmousemove = function (me) {
          const meScaleClientX = me.clientX/that.containerScale
          const meScaleClientY = me.clientY/that.containerScale
          if (binding.value === 'move'){
            cptX = meScaleClientX - disX;
            cptY = meScaleClientY - disY;

            Object.keys(that.cacheChoices).forEach((key)=>{
              that.cacheChoices[key].cptX = that.cacheChoicesFixed[key].cptX + Math.round(meScaleClientX-scaleClientX)
              that.cacheChoices[key].cptY = that.cacheChoicesFixed[key].cptY + Math.round(meScaleClientY-scaleClientY)
            })
          }else{
            switch (binding.value) {
              case 'lt':
                cptWidth = ltX - meScaleClientX;
                cptHeight = ltY - meScaleClientY;
                cptX = meScaleClientX - disX;
                cptY = meScaleClientY - disY;
                that.currentCpt.cptX = Math.round(cptX);
                that.currentCpt.cptY = Math.round(cptY);
                break;
              case 't':
                cptHeight = ltY - meScaleClientY;
                cptY = meScaleClientY - disY;
                that.currentCpt.cptY = Math.round(cptY);
                break;
              case 'rt':
                cptWidth = meScaleClientX - rbX;
                cptHeight = ltY - meScaleClientY;
                cptY = meScaleClientY - disY;
                that.currentCpt.cptY = Math.round(cptY);
                break;
              case 'r':
                cptWidth = meScaleClientX - rbX;
                break;
              case 'rb':
                cptWidth = meScaleClientX - rbX;
                cptHeight = meScaleClientY - rbY;
                break;
              case 'b':
                cptHeight = meScaleClientY - rbY;
                break;
              case 'lb':
                cptWidth = ltX - meScaleClientX;
                cptHeight = meScaleClientY - rbY;
                cptX = meScaleClientX - disX;
                that.currentCpt.cptX = Math.round(cptX);
                break;
              case 'l':
                cptWidth = ltX - meScaleClientX;
                cptX = meScaleClientX - disX;
                that.currentCpt.cptX = Math.round(cptX);
                break;
            }
            cptWidth = cptWidth < 40 ? 40:cptWidth;//限制最小缩放
            cptHeight = cptHeight < 20 ? 20:cptHeight;
            if (cptWidth) that.currentCpt.cptWidth = Math.round(cptWidth);
            if (cptHeight) that.currentCpt.cptHeight = Math.round(cptHeight);
          }
        }
        document.onmouseup = function () {
          document.onmousemove = document.onmouseup = null;
          that.cacheChoicesFixed = JSON.parse(JSON.stringify(that.cacheChoices));//解决多选移动未松开ctrl键第二次以后拖动定位还原
        }
        return false;
      }
    }
  }
}
</script>

<style lang="less" scoped>
.layout-main {
  display: flex;

  &-left {
    height: 100%;
    overflow: hidden;
  }

  &-center {
    flex: 1;
    position: relative;
    overflow: hidden;
    height: 100%;

    &__inner {
      position: relative;
      width: 100%;
      height: calc(100% - 40px);
      overflow: auto;

      &::-webkit-scrollbar-corner {background: rgba(144, 146, 152, 0.3);}
      &::-webkit-scrollbar {width: 8px;height: 8px;}
      &::-webkit-scrollbar-thumb {border-radius: 5px;background: #3C3D42;}
      &::-webkit-scrollbar-track {border-radius: 5px;background: rgba(144, 146, 152, 0.3);}
    }
    &__bottom {
      display: flex;
      justify-content: space-between;
      flex-wrap: nowrap;
      align-items: center;
      padding: 0 10px;
      border: 1px solid;
      height: 40px;
      background-color: var(--bottom-bg);
      border-color: var(--bottom-bd);
    }
  }
}
.top {height: 60px;box-shadow: 0 2px 5px #2b3340 inset;color: #fff;overflow: hidden;
  display: flex;
  align-items: center;
  margin: 0;font-size: 18px;line-height: 45px;background: #353F50}
.webContainer {position: relative;margin: 0 20px;background-size:100% 100%;transform-origin:0 0; transition: all .3s;}
.delTag {width: 45px;height: 22px;background: rgba(43, 51, 64, 0.8);border-radius: 2px;color: #ccc;z-index: 2000;
  position: absolute;top: 0;right: 0;text-align: center;display: none;cursor: pointer
}
.activeMask{width: 100%;height: 100%;position: absolute;z-index: 1801}
.cptDiv{position: absolute;outline:none}
.cptDiv:hover {
  .delTag {display: block}
  .shape-modal {
    border-width: 1px;
  }
}
.resizeTag{width: 8px;height: 8px;position: absolute;background-color: #B6BFCE;z-index: 2000;border-radius: 50%;}
.cptDiv .shape-modal {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  right: 0;
  border: 0px dotted var(--themeColor);
}
.configBtn:hover{cursor: pointer;color: #B6BFCE}
.el-dropdown-link { cursor: pointer; color: #fff;}
.hide {
  display: none;
}
.lock {
  cursor: default !important;
}
</style>
